M2.855 · Modelos avanzados de minería de datos · PEC1
2021-1 · Máster universitario en Ciencia de datos (Data science)
Estudios de Informática, Multimedia y Telecomunicación
A lo largo de esta práctica veremos como aplicar distintas técnicas para la carga y preparación de datos:
Importante: Cada uno de los ejercicios puede suponer varios minutos de ejecución, por lo que la entrega debe hacerse en formato notebook y en formato html, donde se vea el código, los resultados y comentarios de cada ejercicio. Se puede exportar el notebook a html desde el menú File $\to$ Download as $\to$ HTML.
Importante: Existe un tipo de celda especial para albergar texto. Este tipo de celda os será muy útil para responder a las diferentes preguntas teóricas planteadas a lo largo de cada PEC. Para cambiar el tipo de celda a este tipo, en el menú: Cell $\to$ Cell Type $\to$ Markdown.
Para ello vamos a necesitar las siguientes librerías:
from six import StringIO
from IPython.display import Image
from sklearn import datasets
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
from sklearn.tree import DecisionTreeClassifier, export_graphviz, plot_tree
import pydotplus
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
import pandas as pd
pd.set_option('display.max_columns', None)
En primer lugar, deberéis cargar el conjunto de datos Breast Cancer Wisconsin (más información en https://archive.ics.uci.edu/ml/datasets/Breast+Cancer+Wisconsin+(Diagnostic)). Éste se puede descargar de Internet o puede ser cargado directamente usando una librería de "scikit-learn", que incorpora un conjunto de datasets muy conocidos y empleados para minería de datos y machine learning (https://scikit-learn.org/stable/datasets.html).
# Importar dataset mediante la librería de "scikit-learn"
from sklearn.datasets import load_breast_cancer
data, target = load_breast_cancer(return_X_y = True, as_frame = True)
# Convertir target en DataFrame
target = pd.DataFrame(target)
target.dtypes
target int32 dtype: object
# Cambiar tipo de datos a categórico
target = target.astype('category')
print(target.dtypes)
target
target category dtype: object
| target | |
|---|---|
| 0 | 0 |
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| ... | ... |
| 564 | 0 |
| 565 | 0 |
| 566 | 0 |
| 567 | 0 |
| 568 | 1 |
569 rows × 1 columns
# Cambiar valores tal que 0 = Benigno y 1 = Maligno
target["target"].replace({0:"M", 1:"B"}, inplace=True)
target
| target | |
|---|---|
| 0 | M |
| 1 | M |
| 2 | M |
| 3 | M |
| 4 | M |
| ... | ... |
| 564 | M |
| 565 | M |
| 566 | M |
| 567 | M |
| 568 | B |
569 rows × 1 columns
# Consolidar el target y los atributos en un solo DataFrame
bcw = pd.concat([target, data], axis=1)
#Cambiar nombre de la columna target por "diagnosis"
bcw = bcw.rename(columns={"target":"diagnosis"})
bcw
| diagnosis | mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | mean concave points | mean symmetry | mean fractal dimension | radius error | texture error | perimeter error | area error | smoothness error | compactness error | concavity error | concave points error | symmetry error | fractal dimension error | worst radius | worst texture | worst perimeter | worst area | worst smoothness | worst compactness | worst concavity | worst concave points | worst symmetry | worst fractal dimension | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | M | 17.99 | 10.38 | 122.80 | 1001.0 | 0.11840 | 0.27760 | 0.30010 | 0.14710 | 0.2419 | 0.07871 | 1.0950 | 0.9053 | 8.589 | 153.40 | 0.006399 | 0.04904 | 0.05373 | 0.01587 | 0.03003 | 0.006193 | 25.380 | 17.33 | 184.60 | 2019.0 | 0.16220 | 0.66560 | 0.7119 | 0.2654 | 0.4601 | 0.11890 |
| 1 | M | 20.57 | 17.77 | 132.90 | 1326.0 | 0.08474 | 0.07864 | 0.08690 | 0.07017 | 0.1812 | 0.05667 | 0.5435 | 0.7339 | 3.398 | 74.08 | 0.005225 | 0.01308 | 0.01860 | 0.01340 | 0.01389 | 0.003532 | 24.990 | 23.41 | 158.80 | 1956.0 | 0.12380 | 0.18660 | 0.2416 | 0.1860 | 0.2750 | 0.08902 |
| 2 | M | 19.69 | 21.25 | 130.00 | 1203.0 | 0.10960 | 0.15990 | 0.19740 | 0.12790 | 0.2069 | 0.05999 | 0.7456 | 0.7869 | 4.585 | 94.03 | 0.006150 | 0.04006 | 0.03832 | 0.02058 | 0.02250 | 0.004571 | 23.570 | 25.53 | 152.50 | 1709.0 | 0.14440 | 0.42450 | 0.4504 | 0.2430 | 0.3613 | 0.08758 |
| 3 | M | 11.42 | 20.38 | 77.58 | 386.1 | 0.14250 | 0.28390 | 0.24140 | 0.10520 | 0.2597 | 0.09744 | 0.4956 | 1.1560 | 3.445 | 27.23 | 0.009110 | 0.07458 | 0.05661 | 0.01867 | 0.05963 | 0.009208 | 14.910 | 26.50 | 98.87 | 567.7 | 0.20980 | 0.86630 | 0.6869 | 0.2575 | 0.6638 | 0.17300 |
| 4 | M | 20.29 | 14.34 | 135.10 | 1297.0 | 0.10030 | 0.13280 | 0.19800 | 0.10430 | 0.1809 | 0.05883 | 0.7572 | 0.7813 | 5.438 | 94.44 | 0.011490 | 0.02461 | 0.05688 | 0.01885 | 0.01756 | 0.005115 | 22.540 | 16.67 | 152.20 | 1575.0 | 0.13740 | 0.20500 | 0.4000 | 0.1625 | 0.2364 | 0.07678 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 564 | M | 21.56 | 22.39 | 142.00 | 1479.0 | 0.11100 | 0.11590 | 0.24390 | 0.13890 | 0.1726 | 0.05623 | 1.1760 | 1.2560 | 7.673 | 158.70 | 0.010300 | 0.02891 | 0.05198 | 0.02454 | 0.01114 | 0.004239 | 25.450 | 26.40 | 166.10 | 2027.0 | 0.14100 | 0.21130 | 0.4107 | 0.2216 | 0.2060 | 0.07115 |
| 565 | M | 20.13 | 28.25 | 131.20 | 1261.0 | 0.09780 | 0.10340 | 0.14400 | 0.09791 | 0.1752 | 0.05533 | 0.7655 | 2.4630 | 5.203 | 99.04 | 0.005769 | 0.02423 | 0.03950 | 0.01678 | 0.01898 | 0.002498 | 23.690 | 38.25 | 155.00 | 1731.0 | 0.11660 | 0.19220 | 0.3215 | 0.1628 | 0.2572 | 0.06637 |
| 566 | M | 16.60 | 28.08 | 108.30 | 858.1 | 0.08455 | 0.10230 | 0.09251 | 0.05302 | 0.1590 | 0.05648 | 0.4564 | 1.0750 | 3.425 | 48.55 | 0.005903 | 0.03731 | 0.04730 | 0.01557 | 0.01318 | 0.003892 | 18.980 | 34.12 | 126.70 | 1124.0 | 0.11390 | 0.30940 | 0.3403 | 0.1418 | 0.2218 | 0.07820 |
| 567 | M | 20.60 | 29.33 | 140.10 | 1265.0 | 0.11780 | 0.27700 | 0.35140 | 0.15200 | 0.2397 | 0.07016 | 0.7260 | 1.5950 | 5.772 | 86.22 | 0.006522 | 0.06158 | 0.07117 | 0.01664 | 0.02324 | 0.006185 | 25.740 | 39.42 | 184.60 | 1821.0 | 0.16500 | 0.86810 | 0.9387 | 0.2650 | 0.4087 | 0.12400 |
| 568 | B | 7.76 | 24.54 | 47.92 | 181.0 | 0.05263 | 0.04362 | 0.00000 | 0.00000 | 0.1587 | 0.05884 | 0.3857 | 1.4280 | 2.548 | 19.15 | 0.007189 | 0.00466 | 0.00000 | 0.00000 | 0.02676 | 0.002783 | 9.456 | 30.37 | 59.16 | 268.6 | 0.08996 | 0.06444 | 0.0000 | 0.0000 | 0.2871 | 0.07039 |
569 rows × 31 columns
bcw.dtypes
diagnosis object mean radius float64 mean texture float64 mean perimeter float64 mean area float64 mean smoothness float64 mean compactness float64 mean concavity float64 mean concave points float64 mean symmetry float64 mean fractal dimension float64 radius error float64 texture error float64 perimeter error float64 area error float64 smoothness error float64 compactness error float64 concavity error float64 concave points error float64 symmetry error float64 fractal dimension error float64 worst radius float64 worst texture float64 worst perimeter float64 worst area float64 worst smoothness float64 worst compactness float64 worst concavity float64 worst concave points float64 worst symmetry float64 worst fractal dimension float64 dtype: object
Vamos a modificar el tipo de datos de la columna target a categórico, puesto que al crear el dataframe conjunto se ha establecido como objeto.
bcw["diagnosis"] = bcw.diagnosis.astype('category')
bcw.dtypes
diagnosis category mean radius float64 mean texture float64 mean perimeter float64 mean area float64 mean smoothness float64 mean compactness float64 mean concavity float64 mean concave points float64 mean symmetry float64 mean fractal dimension float64 radius error float64 texture error float64 perimeter error float64 area error float64 smoothness error float64 compactness error float64 concavity error float64 concave points error float64 symmetry error float64 fractal dimension error float64 worst radius float64 worst texture float64 worst perimeter float64 worst area float64 worst smoothness float64 worst compactness float64 worst concavity float64 worst concave points float64 worst symmetry float64 worst fractal dimension float64 dtype: object
# Mostrar nº de filas y columnas (atributos)
bcw.shape
(569, 31)
Como se puede ver, el dataset cuenta con 569 filas y 30 atributos (más la columna target), cuyos nombres son los siguientes:
# Mostrar nombre de las columnas (atributos)
bcw.columns
Index(['diagnosis', 'mean radius', 'mean texture', 'mean perimeter',
'mean area', 'mean smoothness', 'mean compactness', 'mean concavity',
'mean concave points', 'mean symmetry', 'mean fractal dimension',
'radius error', 'texture error', 'perimeter error', 'area error',
'smoothness error', 'compactness error', 'concavity error',
'concave points error', 'symmetry error', 'fractal dimension error',
'worst radius', 'worst texture', 'worst perimeter', 'worst area',
'worst smoothness', 'worst compactness', 'worst concavity',
'worst concave points', 'worst symmetry', 'worst fractal dimension'],
dtype='object')
Ahora comprobaremos si existen missing values en el conjunto de datos.
# Comprobar si existen datos NaN o NULL
if (bcw.isna().sum().sum() + bcw.isnull().sum().sum() == 0):
print("No hay datos vacíos ni nulos")
else: print("Hay datos vacíos o nulos")
# Mostrar el nº de valores NaN o NULL por columnas y el total
print("\nValores vacíos o nulos por columnas:\n")
print(bcw.isna().sum() + bcw.isnull().sum())
print("\nTotal: ", bcw.isna().sum().sum() + bcw.isnull().sum().sum())
No hay datos vacíos ni nulos Valores vacíos o nulos por columnas: diagnosis 0 mean radius 0 mean texture 0 mean perimeter 0 mean area 0 mean smoothness 0 mean compactness 0 mean concavity 0 mean concave points 0 mean symmetry 0 mean fractal dimension 0 radius error 0 texture error 0 perimeter error 0 area error 0 smoothness error 0 compactness error 0 concavity error 0 concave points error 0 symmetry error 0 fractal dimension error 0 worst radius 0 worst texture 0 worst perimeter 0 worst area 0 worst smoothness 0 worst compactness 0 worst concavity 0 worst concave points 0 worst symmetry 0 worst fractal dimension 0 dtype: int64 Total: 0
Como no hay valores vacíos ni nulos, no se requiere comprobar cuántos corresponden a vacíos (NaN) y cuántos a nulos (NULL). Sin embargo, puede que los datos vacíos estén codificados como 0, por lo que buscaremos estos tipos de datos.
# Mostrar el nº de valores = 0 por columnas y el total
print("\nValores vacíos o nulos por columnas:\n")
print(bcw.isin([0]).sum())
print("\nTotal: ", bcw.isin([0]).sum().sum())
Valores vacíos o nulos por columnas: diagnosis 0 mean radius 0 mean texture 0 mean perimeter 0 mean area 0 mean smoothness 0 mean compactness 0 mean concavity 13 mean concave points 13 mean symmetry 0 mean fractal dimension 0 radius error 0 texture error 0 perimeter error 0 area error 0 smoothness error 0 compactness error 0 concavity error 13 concave points error 13 symmetry error 0 fractal dimension error 0 worst radius 0 worst texture 0 worst perimeter 0 worst area 0 worst smoothness 0 worst compactness 0 worst concavity 13 worst concave points 13 worst symmetry 0 worst fractal dimension 0 dtype: int64 Total: 78
Vemos que hay 13 registros que tienen el valor 0 en las columnas mean concavity y mean concave points, que resultan por tanto en el valor 0 de los atributos derivados de éstas: concavity error, concave point error, worst concavity y worst concave points.
Como ya hemos visto anteriormente, solo la columna target es de tipo categórico, por lo que representaremos los valores de esta columna únicamente.
# Graficar valores de la columna "diagnosis"
print(bcw["diagnosis"].value_counts())
bcw["diagnosis"].value_counts().plot(kind="bar", title="Diagnóstico de las pacientes", xlabel="Tipo",
ylabel="Nº de casos").set_xticklabels(["Benigno", "Maligno"], rotation=0)
B 357 M 212 Name: diagnosis, dtype: int64
[Text(0, 0, 'Benigno'), Text(1, 0, 'Maligno')]
# Mostrar media y desviación estándar de cada uno de los atributos
bcw.describe().loc[["mean", "std"]]
| mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | mean concave points | mean symmetry | mean fractal dimension | radius error | texture error | perimeter error | area error | smoothness error | compactness error | concavity error | concave points error | symmetry error | fractal dimension error | worst radius | worst texture | worst perimeter | worst area | worst smoothness | worst compactness | worst concavity | worst concave points | worst symmetry | worst fractal dimension | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| mean | 14.127292 | 19.289649 | 91.969033 | 654.889104 | 0.096360 | 0.104341 | 0.088799 | 0.048919 | 0.181162 | 0.062798 | 0.405172 | 1.216853 | 2.866059 | 40.337079 | 0.007041 | 0.025478 | 0.031894 | 0.011796 | 0.020542 | 0.003795 | 16.269190 | 25.677223 | 107.261213 | 880.583128 | 0.132369 | 0.254265 | 0.272188 | 0.114606 | 0.290076 | 0.083946 |
| std | 3.524049 | 4.301036 | 24.298981 | 351.914129 | 0.014064 | 0.052813 | 0.079720 | 0.038803 | 0.027414 | 0.007060 | 0.277313 | 0.551648 | 2.021855 | 45.491006 | 0.003003 | 0.017908 | 0.030186 | 0.006170 | 0.008266 | 0.002646 | 4.833242 | 6.146258 | 33.602542 | 569.356993 | 0.022832 | 0.157336 | 0.208624 | 0.065732 | 0.061867 | 0.018061 |
Al ser todos los atributos de tipo numérico, se puede aplicar la estadística descriptiva sobre cada uno de ellos. De esta forma obtenemos medidas como la media y la desviación estándar de todos los registros por cada atributo individual. Con estas medidas nos podemos hacer una idea de la magnitud y distribución de las variable. Por ejemplo, sabemos que la media del radio de todas las mediciones es 14.127, con una desviación estándar de 3.524. Conocer la distribución de los datos es el primer paso para un futuro análisis más profundo, mediante el que podamos obtener conclusiones más complejas.
En este ejercicio vamos a explorar la relación de algunos de los atributos numéricos con la variable respuesta ("Diagnosis"), tanto gráficamente como cuantitativamente y analizaremos las distintas correlaciones. Para empezar, seleccionad los 4 atributos que queréis explorar. Si habéis usado los nombres de columnas proporcionados por sklearn, una lista de posibles nombres de atributos serían:
feats_to_explore = ['mean radius', 'mean texture', 'mean smoothness', 'mean symmetry']
# Crear 4 gráficos, 1 por cada variable
for i in range(len(feats_to_explore)):
plt.figure(figsize=(15,5))
plt.title(feats_to_explore[i])
# Cada gráfico debe dividir los registros según los valores de la clase (diagnosis) y mostrarlos de forma separada
for j in bcw["diagnosis"].unique():
plt.hist(bcw[feats_to_explore[i]].loc[bcw["diagnosis"]==j], alpha=.75)
plt.legend(bcw["diagnosis"].unique())
plt.xlabel("Magnitud")
plt.ylabel("Frecuencia")
plt.show()
De los 4 atributos, mean radius es el que mejor separa los valores del diagnóstico debido a la pequeña intersección entre las medidas con diagnóstico benigno y con diagnóstico maligno. Se puede apreciar que las pacientes con un radio menor de 14 tienen altas probabilidades de tener un diagnóstico benigno, mientras que si el radio es mayor que 14 las probabilidades de tener un diagnóstico maligno son muy elevadas.
Con algo más de incertidumbre, especialmente en los valores centrales de la distribución, mean textue podría separar los registros según la clase con relativa claridad, aunque la área superpuesta por ambos histogramas es mayor que en anterior caso.
Por otro lado, en cuanto al atributo mean smoothness, las probabilidades de recibir un falso positivo son muy altas debido a que casi todos los pocos casos de diagnóstico maligno se superponen con los de diagnóstico benigno.
Al igual que en el caso anterior, el atributo mean symmetry no da apenas información por sí mismo acerca del diagnóstico. Esto se debe al gran área superpuesta entre las pacientes que reciben distintos diagnósticos, siendo este atributo junto a mean smoothness los peores de los 4 atributos analizados para establecer este tipo de conclusiones.
# Obtenemos la media y la desviación estándar de los atributos para los diagnósticos benignos
print("Casos con diagnóstico BENIGNO")
bcw[feats_to_explore].loc[bcw["diagnosis"]=="B"].describe().loc[["mean", "std"]]
Casos con diagnóstico BENIGNO
| mean radius | mean texture | mean smoothness | mean symmetry | |
|---|---|---|---|---|
| mean | 12.146524 | 17.914762 | 0.092478 | 0.174186 |
| std | 1.780512 | 3.995125 | 0.013446 | 0.024807 |
# Obtenemos la media y la desviación estándar de los atributos para los diagnósticos malignos
print("Casos con diagnóstico MALIGNO")
bcw[feats_to_explore].loc[bcw["diagnosis"]=="M"].describe().loc[["mean", "std"]]
Casos con diagnóstico MALIGNO
| mean radius | mean texture | mean smoothness | mean symmetry | |
|---|---|---|---|---|
| mean | 17.462830 | 21.604906 | 0.102898 | 0.192909 |
| std | 3.203971 | 3.779470 | 0.012608 | 0.027638 |
Observando las distribuciones mediante la media y la desviación estándar se hace más evidente cuáles atributos dan más información sobre la clase y cuáles menos. Mean radius y mean texture presentan una mayor diferencia en su media dependiento del tipo de diagnóstico, con una desviación estándar los suficientemente pequeña como para saber que la distribución de los datos podrían determinar la clase con una incertidumbre relativamente baja.
También se evidencia con los atributos mean smoothness y mean symmetry presentan una media y una distribución muy similar en ambas categorías de diagnóstico.
# Obtener la matriz de correlación con todos los atributos
bcw.corr()
| mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | mean concave points | mean symmetry | mean fractal dimension | radius error | texture error | perimeter error | area error | smoothness error | compactness error | concavity error | concave points error | symmetry error | fractal dimension error | worst radius | worst texture | worst perimeter | worst area | worst smoothness | worst compactness | worst concavity | worst concave points | worst symmetry | worst fractal dimension | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| mean radius | 1.000000 | 0.323782 | 0.997855 | 0.987357 | 0.170581 | 0.506124 | 0.676764 | 0.822529 | 0.147741 | -0.311631 | 0.679090 | -0.097317 | 0.674172 | 0.735864 | -0.222600 | 0.206000 | 0.194204 | 0.376169 | -0.104321 | -0.042641 | 0.969539 | 0.297008 | 0.965137 | 0.941082 | 0.119616 | 0.413463 | 0.526911 | 0.744214 | 0.163953 | 0.007066 |
| mean texture | 0.323782 | 1.000000 | 0.329533 | 0.321086 | -0.023389 | 0.236702 | 0.302418 | 0.293464 | 0.071401 | -0.076437 | 0.275869 | 0.386358 | 0.281673 | 0.259845 | 0.006614 | 0.191975 | 0.143293 | 0.163851 | 0.009127 | 0.054458 | 0.352573 | 0.912045 | 0.358040 | 0.343546 | 0.077503 | 0.277830 | 0.301025 | 0.295316 | 0.105008 | 0.119205 |
| mean perimeter | 0.997855 | 0.329533 | 1.000000 | 0.986507 | 0.207278 | 0.556936 | 0.716136 | 0.850977 | 0.183027 | -0.261477 | 0.691765 | -0.086761 | 0.693135 | 0.744983 | -0.202694 | 0.250744 | 0.228082 | 0.407217 | -0.081629 | -0.005523 | 0.969476 | 0.303038 | 0.970387 | 0.941550 | 0.150549 | 0.455774 | 0.563879 | 0.771241 | 0.189115 | 0.051019 |
| mean area | 0.987357 | 0.321086 | 0.986507 | 1.000000 | 0.177028 | 0.498502 | 0.685983 | 0.823269 | 0.151293 | -0.283110 | 0.732562 | -0.066280 | 0.726628 | 0.800086 | -0.166777 | 0.212583 | 0.207660 | 0.372320 | -0.072497 | -0.019887 | 0.962746 | 0.287489 | 0.959120 | 0.959213 | 0.123523 | 0.390410 | 0.512606 | 0.722017 | 0.143570 | 0.003738 |
| mean smoothness | 0.170581 | -0.023389 | 0.207278 | 0.177028 | 1.000000 | 0.659123 | 0.521984 | 0.553695 | 0.557775 | 0.584792 | 0.301467 | 0.068406 | 0.296092 | 0.246552 | 0.332375 | 0.318943 | 0.248396 | 0.380676 | 0.200774 | 0.283607 | 0.213120 | 0.036072 | 0.238853 | 0.206718 | 0.805324 | 0.472468 | 0.434926 | 0.503053 | 0.394309 | 0.499316 |
| mean compactness | 0.506124 | 0.236702 | 0.556936 | 0.498502 | 0.659123 | 1.000000 | 0.883121 | 0.831135 | 0.602641 | 0.565369 | 0.497473 | 0.046205 | 0.548905 | 0.455653 | 0.135299 | 0.738722 | 0.570517 | 0.642262 | 0.229977 | 0.507318 | 0.535315 | 0.248133 | 0.590210 | 0.509604 | 0.565541 | 0.865809 | 0.816275 | 0.815573 | 0.510223 | 0.687382 |
| mean concavity | 0.676764 | 0.302418 | 0.716136 | 0.685983 | 0.521984 | 0.883121 | 1.000000 | 0.921391 | 0.500667 | 0.336783 | 0.631925 | 0.076218 | 0.660391 | 0.617427 | 0.098564 | 0.670279 | 0.691270 | 0.683260 | 0.178009 | 0.449301 | 0.688236 | 0.299879 | 0.729565 | 0.675987 | 0.448822 | 0.754968 | 0.884103 | 0.861323 | 0.409464 | 0.514930 |
| mean concave points | 0.822529 | 0.293464 | 0.850977 | 0.823269 | 0.553695 | 0.831135 | 0.921391 | 1.000000 | 0.462497 | 0.166917 | 0.698050 | 0.021480 | 0.710650 | 0.690299 | 0.027653 | 0.490424 | 0.439167 | 0.615634 | 0.095351 | 0.257584 | 0.830318 | 0.292752 | 0.855923 | 0.809630 | 0.452753 | 0.667454 | 0.752399 | 0.910155 | 0.375744 | 0.368661 |
| mean symmetry | 0.147741 | 0.071401 | 0.183027 | 0.151293 | 0.557775 | 0.602641 | 0.500667 | 0.462497 | 1.000000 | 0.479921 | 0.303379 | 0.128053 | 0.313893 | 0.223970 | 0.187321 | 0.421659 | 0.342627 | 0.393298 | 0.449137 | 0.331786 | 0.185728 | 0.090651 | 0.219169 | 0.177193 | 0.426675 | 0.473200 | 0.433721 | 0.430297 | 0.699826 | 0.438413 |
| mean fractal dimension | -0.311631 | -0.076437 | -0.261477 | -0.283110 | 0.584792 | 0.565369 | 0.336783 | 0.166917 | 0.479921 | 1.000000 | 0.000111 | 0.164174 | 0.039830 | -0.090170 | 0.401964 | 0.559837 | 0.446630 | 0.341198 | 0.345007 | 0.688132 | -0.253691 | -0.051269 | -0.205151 | -0.231854 | 0.504942 | 0.458798 | 0.346234 | 0.175325 | 0.334019 | 0.767297 |
| radius error | 0.679090 | 0.275869 | 0.691765 | 0.732562 | 0.301467 | 0.497473 | 0.631925 | 0.698050 | 0.303379 | 0.000111 | 1.000000 | 0.213247 | 0.972794 | 0.951830 | 0.164514 | 0.356065 | 0.332358 | 0.513346 | 0.240567 | 0.227754 | 0.715065 | 0.194799 | 0.719684 | 0.751548 | 0.141919 | 0.287103 | 0.380585 | 0.531062 | 0.094543 | 0.049559 |
| texture error | -0.097317 | 0.386358 | -0.086761 | -0.066280 | 0.068406 | 0.046205 | 0.076218 | 0.021480 | 0.128053 | 0.164174 | 0.213247 | 1.000000 | 0.223171 | 0.111567 | 0.397243 | 0.231700 | 0.194998 | 0.230283 | 0.411621 | 0.279723 | -0.111690 | 0.409003 | -0.102242 | -0.083195 | -0.073658 | -0.092439 | -0.068956 | -0.119638 | -0.128215 | -0.045655 |
| perimeter error | 0.674172 | 0.281673 | 0.693135 | 0.726628 | 0.296092 | 0.548905 | 0.660391 | 0.710650 | 0.313893 | 0.039830 | 0.972794 | 0.223171 | 1.000000 | 0.937655 | 0.151075 | 0.416322 | 0.362482 | 0.556264 | 0.266487 | 0.244143 | 0.697201 | 0.200371 | 0.721031 | 0.730713 | 0.130054 | 0.341919 | 0.418899 | 0.554897 | 0.109930 | 0.085433 |
| area error | 0.735864 | 0.259845 | 0.744983 | 0.800086 | 0.246552 | 0.455653 | 0.617427 | 0.690299 | 0.223970 | -0.090170 | 0.951830 | 0.111567 | 0.937655 | 1.000000 | 0.075150 | 0.284840 | 0.270895 | 0.415730 | 0.134109 | 0.127071 | 0.757373 | 0.196497 | 0.761213 | 0.811408 | 0.125389 | 0.283257 | 0.385100 | 0.538166 | 0.074126 | 0.017539 |
| smoothness error | -0.222600 | 0.006614 | -0.202694 | -0.166777 | 0.332375 | 0.135299 | 0.098564 | 0.027653 | 0.187321 | 0.401964 | 0.164514 | 0.397243 | 0.151075 | 0.075150 | 1.000000 | 0.336696 | 0.268685 | 0.328429 | 0.413506 | 0.427374 | -0.230691 | -0.074743 | -0.217304 | -0.182195 | 0.314457 | -0.055558 | -0.058298 | -0.102007 | -0.107342 | 0.101480 |
| compactness error | 0.206000 | 0.191975 | 0.250744 | 0.212583 | 0.318943 | 0.738722 | 0.670279 | 0.490424 | 0.421659 | 0.559837 | 0.356065 | 0.231700 | 0.416322 | 0.284840 | 0.336696 | 1.000000 | 0.801268 | 0.744083 | 0.394713 | 0.803269 | 0.204607 | 0.143003 | 0.260516 | 0.199371 | 0.227394 | 0.678780 | 0.639147 | 0.483208 | 0.277878 | 0.590973 |
| concavity error | 0.194204 | 0.143293 | 0.228082 | 0.207660 | 0.248396 | 0.570517 | 0.691270 | 0.439167 | 0.342627 | 0.446630 | 0.332358 | 0.194998 | 0.362482 | 0.270895 | 0.268685 | 0.801268 | 1.000000 | 0.771804 | 0.309429 | 0.727372 | 0.186904 | 0.100241 | 0.226680 | 0.188353 | 0.168481 | 0.484858 | 0.662564 | 0.440472 | 0.197788 | 0.439329 |
| concave points error | 0.376169 | 0.163851 | 0.407217 | 0.372320 | 0.380676 | 0.642262 | 0.683260 | 0.615634 | 0.393298 | 0.341198 | 0.513346 | 0.230283 | 0.556264 | 0.415730 | 0.328429 | 0.744083 | 0.771804 | 1.000000 | 0.312780 | 0.611044 | 0.358127 | 0.086741 | 0.394999 | 0.342271 | 0.215351 | 0.452888 | 0.549592 | 0.602450 | 0.143116 | 0.310655 |
| symmetry error | -0.104321 | 0.009127 | -0.081629 | -0.072497 | 0.200774 | 0.229977 | 0.178009 | 0.095351 | 0.449137 | 0.345007 | 0.240567 | 0.411621 | 0.266487 | 0.134109 | 0.413506 | 0.394713 | 0.309429 | 0.312780 | 1.000000 | 0.369078 | -0.128121 | -0.077473 | -0.103753 | -0.110343 | -0.012662 | 0.060255 | 0.037119 | -0.030413 | 0.389402 | 0.078079 |
| fractal dimension error | -0.042641 | 0.054458 | -0.005523 | -0.019887 | 0.283607 | 0.507318 | 0.449301 | 0.257584 | 0.331786 | 0.688132 | 0.227754 | 0.279723 | 0.244143 | 0.127071 | 0.427374 | 0.803269 | 0.727372 | 0.611044 | 0.369078 | 1.000000 | -0.037488 | -0.003195 | -0.001000 | -0.022736 | 0.170568 | 0.390159 | 0.379975 | 0.215204 | 0.111094 | 0.591328 |
| worst radius | 0.969539 | 0.352573 | 0.969476 | 0.962746 | 0.213120 | 0.535315 | 0.688236 | 0.830318 | 0.185728 | -0.253691 | 0.715065 | -0.111690 | 0.697201 | 0.757373 | -0.230691 | 0.204607 | 0.186904 | 0.358127 | -0.128121 | -0.037488 | 1.000000 | 0.359921 | 0.993708 | 0.984015 | 0.216574 | 0.475820 | 0.573975 | 0.787424 | 0.243529 | 0.093492 |
| worst texture | 0.297008 | 0.912045 | 0.303038 | 0.287489 | 0.036072 | 0.248133 | 0.299879 | 0.292752 | 0.090651 | -0.051269 | 0.194799 | 0.409003 | 0.200371 | 0.196497 | -0.074743 | 0.143003 | 0.100241 | 0.086741 | -0.077473 | -0.003195 | 0.359921 | 1.000000 | 0.365098 | 0.345842 | 0.225429 | 0.360832 | 0.368366 | 0.359755 | 0.233027 | 0.219122 |
| worst perimeter | 0.965137 | 0.358040 | 0.970387 | 0.959120 | 0.238853 | 0.590210 | 0.729565 | 0.855923 | 0.219169 | -0.205151 | 0.719684 | -0.102242 | 0.721031 | 0.761213 | -0.217304 | 0.260516 | 0.226680 | 0.394999 | -0.103753 | -0.001000 | 0.993708 | 0.365098 | 1.000000 | 0.977578 | 0.236775 | 0.529408 | 0.618344 | 0.816322 | 0.269493 | 0.138957 |
| worst area | 0.941082 | 0.343546 | 0.941550 | 0.959213 | 0.206718 | 0.509604 | 0.675987 | 0.809630 | 0.177193 | -0.231854 | 0.751548 | -0.083195 | 0.730713 | 0.811408 | -0.182195 | 0.199371 | 0.188353 | 0.342271 | -0.110343 | -0.022736 | 0.984015 | 0.345842 | 0.977578 | 1.000000 | 0.209145 | 0.438296 | 0.543331 | 0.747419 | 0.209146 | 0.079647 |
| worst smoothness | 0.119616 | 0.077503 | 0.150549 | 0.123523 | 0.805324 | 0.565541 | 0.448822 | 0.452753 | 0.426675 | 0.504942 | 0.141919 | -0.073658 | 0.130054 | 0.125389 | 0.314457 | 0.227394 | 0.168481 | 0.215351 | -0.012662 | 0.170568 | 0.216574 | 0.225429 | 0.236775 | 0.209145 | 1.000000 | 0.568187 | 0.518523 | 0.547691 | 0.493838 | 0.617624 |
| worst compactness | 0.413463 | 0.277830 | 0.455774 | 0.390410 | 0.472468 | 0.865809 | 0.754968 | 0.667454 | 0.473200 | 0.458798 | 0.287103 | -0.092439 | 0.341919 | 0.283257 | -0.055558 | 0.678780 | 0.484858 | 0.452888 | 0.060255 | 0.390159 | 0.475820 | 0.360832 | 0.529408 | 0.438296 | 0.568187 | 1.000000 | 0.892261 | 0.801080 | 0.614441 | 0.810455 |
| worst concavity | 0.526911 | 0.301025 | 0.563879 | 0.512606 | 0.434926 | 0.816275 | 0.884103 | 0.752399 | 0.433721 | 0.346234 | 0.380585 | -0.068956 | 0.418899 | 0.385100 | -0.058298 | 0.639147 | 0.662564 | 0.549592 | 0.037119 | 0.379975 | 0.573975 | 0.368366 | 0.618344 | 0.543331 | 0.518523 | 0.892261 | 1.000000 | 0.855434 | 0.532520 | 0.686511 |
| worst concave points | 0.744214 | 0.295316 | 0.771241 | 0.722017 | 0.503053 | 0.815573 | 0.861323 | 0.910155 | 0.430297 | 0.175325 | 0.531062 | -0.119638 | 0.554897 | 0.538166 | -0.102007 | 0.483208 | 0.440472 | 0.602450 | -0.030413 | 0.215204 | 0.787424 | 0.359755 | 0.816322 | 0.747419 | 0.547691 | 0.801080 | 0.855434 | 1.000000 | 0.502528 | 0.511114 |
| worst symmetry | 0.163953 | 0.105008 | 0.189115 | 0.143570 | 0.394309 | 0.510223 | 0.409464 | 0.375744 | 0.699826 | 0.334019 | 0.094543 | -0.128215 | 0.109930 | 0.074126 | -0.107342 | 0.277878 | 0.197788 | 0.143116 | 0.389402 | 0.111094 | 0.243529 | 0.233027 | 0.269493 | 0.209146 | 0.493838 | 0.614441 | 0.532520 | 0.502528 | 1.000000 | 0.537848 |
| worst fractal dimension | 0.007066 | 0.119205 | 0.051019 | 0.003738 | 0.499316 | 0.687382 | 0.514930 | 0.368661 | 0.438413 | 0.767297 | 0.049559 | -0.045655 | 0.085433 | 0.017539 | 0.101480 | 0.590973 | 0.439329 | 0.310655 | 0.078079 | 0.591328 | 0.093492 | 0.219122 | 0.138957 | 0.079647 | 0.617624 | 0.810455 | 0.686511 | 0.511114 | 0.537848 | 1.000000 |
# Generar graficos de relaciones por pares de atributos
sns.pairplot(bcw.iloc[:,0:11])
plt.show()
Adicionalmente, se pueden observar estas correlaciones de forma sencilla a través de un mapa de calor, que consume menos recursos computacionalmente.
# Generar mapa de calor a partir de la matriz de correlación
plt.matshow(bcw.iloc[:,0:11].corr())
plt.xticks(range(bcw.iloc[:,0:11].select_dtypes(['number']).shape[1]), bcw.iloc[:,0:11].select_dtypes(['number']).columns, rotation=90)
plt.yticks(range(bcw.iloc[:,0:11].select_dtypes(['number']).shape[1]), bcw.iloc[:,0:11].select_dtypes(['number']).columns)
plt.colorbar()
plt.show()
# Craer dataframe con la misma estructura que la matriz de correlación
# pero registrando True si la correlación entre pares es mayor que 0.9 y menor que 1, y False en otro caso.
corr = bcw.corr()
high_corr = corr
for i in range(corr.shape[0]):
for j in range(corr.shape[1]):
if (corr.iloc[i,j] > .9) & (corr.iloc[i,j] < 1):
high_corr.iloc[i,j] = True
else: high_corr.iloc[i,j] = False
high_corr
| mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | mean concave points | mean symmetry | mean fractal dimension | radius error | texture error | perimeter error | area error | smoothness error | compactness error | concavity error | concave points error | symmetry error | fractal dimension error | worst radius | worst texture | worst perimeter | worst area | worst smoothness | worst compactness | worst concavity | worst concave points | worst symmetry | worst fractal dimension | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| mean radius | False | False | True | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | True | True | False | False | False | False | False | False |
| mean texture | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | False | False | False | False | False | False |
| mean perimeter | True | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | True | True | False | False | False | False | False | False |
| mean area | True | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | True | True | False | False | False | False | False | False |
| mean smoothness | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| mean compactness | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| mean concavity | False | False | False | False | False | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| mean concave points | False | False | False | False | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False |
| mean symmetry | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| mean fractal dimension | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| radius error | False | False | False | False | False | False | False | False | False | False | False | False | True | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| texture error | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| perimeter error | False | False | False | False | False | False | False | False | False | False | True | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| area error | False | False | False | False | False | False | False | False | False | False | True | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| smoothness error | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| compactness error | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| concavity error | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| concave points error | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| symmetry error | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| fractal dimension error | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| worst radius | True | False | True | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | True | False | False | False | False | False | False |
| worst texture | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| worst perimeter | True | False | True | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | False | True | False | False | False | False | False | False |
| worst area | True | False | True | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | True | False | True | False | False | False | False | False | False | False |
| worst smoothness | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| worst compactness | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| worst concavity | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| worst concave points | False | False | False | False | False | False | False | True | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| worst symmetry | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
| worst fractal dimension | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False | False |
# Eliminar las columnas del dataframe original que no tengan al menos un True entre todas las filas del dataframe high_corr
bcw_low_corr = bcw.drop(["diagnosis"], 1)
for i in range(corr.shape[0]):
for j in range(corr.shape[1]):
if high_corr.iloc[j,i]:
bcw_low_corr = bcw_low_corr.drop([bcw.columns[i+1]], 1)
print("Se ha eliminado la columna \033[1m" + bcw.columns[i+1] + "\033[0m")
break
bcw_low_corr
Se ha eliminado la columna mean radius Se ha eliminado la columna mean texture Se ha eliminado la columna mean perimeter Se ha eliminado la columna mean area Se ha eliminado la columna mean concavity Se ha eliminado la columna mean concave points Se ha eliminado la columna radius error Se ha eliminado la columna perimeter error Se ha eliminado la columna area error Se ha eliminado la columna worst radius Se ha eliminado la columna worst texture Se ha eliminado la columna worst perimeter Se ha eliminado la columna worst area Se ha eliminado la columna worst concave points
| mean smoothness | mean compactness | mean symmetry | mean fractal dimension | texture error | smoothness error | compactness error | concavity error | concave points error | symmetry error | fractal dimension error | worst smoothness | worst compactness | worst concavity | worst symmetry | worst fractal dimension | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.11840 | 0.27760 | 0.2419 | 0.07871 | 0.9053 | 0.006399 | 0.04904 | 0.05373 | 0.01587 | 0.03003 | 0.006193 | 0.16220 | 0.66560 | 0.7119 | 0.4601 | 0.11890 |
| 1 | 0.08474 | 0.07864 | 0.1812 | 0.05667 | 0.7339 | 0.005225 | 0.01308 | 0.01860 | 0.01340 | 0.01389 | 0.003532 | 0.12380 | 0.18660 | 0.2416 | 0.2750 | 0.08902 |
| 2 | 0.10960 | 0.15990 | 0.2069 | 0.05999 | 0.7869 | 0.006150 | 0.04006 | 0.03832 | 0.02058 | 0.02250 | 0.004571 | 0.14440 | 0.42450 | 0.4504 | 0.3613 | 0.08758 |
| 3 | 0.14250 | 0.28390 | 0.2597 | 0.09744 | 1.1560 | 0.009110 | 0.07458 | 0.05661 | 0.01867 | 0.05963 | 0.009208 | 0.20980 | 0.86630 | 0.6869 | 0.6638 | 0.17300 |
| 4 | 0.10030 | 0.13280 | 0.1809 | 0.05883 | 0.7813 | 0.011490 | 0.02461 | 0.05688 | 0.01885 | 0.01756 | 0.005115 | 0.13740 | 0.20500 | 0.4000 | 0.2364 | 0.07678 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 564 | 0.11100 | 0.11590 | 0.1726 | 0.05623 | 1.2560 | 0.010300 | 0.02891 | 0.05198 | 0.02454 | 0.01114 | 0.004239 | 0.14100 | 0.21130 | 0.4107 | 0.2060 | 0.07115 |
| 565 | 0.09780 | 0.10340 | 0.1752 | 0.05533 | 2.4630 | 0.005769 | 0.02423 | 0.03950 | 0.01678 | 0.01898 | 0.002498 | 0.11660 | 0.19220 | 0.3215 | 0.2572 | 0.06637 |
| 566 | 0.08455 | 0.10230 | 0.1590 | 0.05648 | 1.0750 | 0.005903 | 0.03731 | 0.04730 | 0.01557 | 0.01318 | 0.003892 | 0.11390 | 0.30940 | 0.3403 | 0.2218 | 0.07820 |
| 567 | 0.11780 | 0.27700 | 0.2397 | 0.07016 | 1.5950 | 0.006522 | 0.06158 | 0.07117 | 0.01664 | 0.02324 | 0.006185 | 0.16500 | 0.86810 | 0.9387 | 0.4087 | 0.12400 |
| 568 | 0.05263 | 0.04362 | 0.1587 | 0.05884 | 1.4280 | 0.007189 | 0.00466 | 0.00000 | 0.00000 | 0.02676 | 0.002783 | 0.08996 | 0.06444 | 0.0000 | 0.2871 | 0.07039 |
569 rows × 16 columns
Las variables eliminadas han sido las 14 impresas en negrita en el output anterior. Al eliminar estas variables, el conjunto de datos ha perdido gran parte de su información intríseca relativa a la distinción entre un diagnóstico y otro, ya que eran estas variables eliminadas las que aportaban dicha información.
El test de Kolmogorov–Smirnov consiste en medir la distancia entre distribuciones teniendo en cuento la media y la dispersión de los datos, por lo que podría resultar de gran utilidad en este caso. Para ello, calcula la función acumulada de cada distribución y mide su distancia vertical, logrando así evaluar la diferencia tanto de las medidas de centro como de dispersión de las distribuciones. Tras realizar el contraste de hipótesis, la función en Python devuelve el valor static y el p-value. Cuanto menor sea este último, más diferentes serán las distribuciones comparadas; y al revés con el valor static.
# Importar el test de Kolmogorov-Smirnov
from scipy.stats import ks_2samp
# Eliminar la columna diagnosis
bcw_ft = bcw.drop(["diagnosis"], 1)
# Crear DF vacío para registrar los resultados
res = pd.DataFrame()
# Divididir cada atributo entre el nº de clases para evaluar las variables disociadas.
for i in range(bcw_ft.shape[1]):
res[bcw_ft.columns[i]] = ks_2samp(bcw_ft.loc[bcw["diagnosis"]=="B"].iloc[i], bcw_ft.loc[bcw["diagnosis"]=="M"].iloc[i])
# Renombrar las filas para indicar el valor que representan
res = res.rename(index={0:"Static", 1:"p-value"})
res
| mean radius | mean texture | mean perimeter | mean area | mean smoothness | mean compactness | mean concavity | mean concave points | mean symmetry | mean fractal dimension | radius error | texture error | perimeter error | area error | smoothness error | compactness error | concavity error | concave points error | symmetry error | fractal dimension error | worst radius | worst texture | worst perimeter | worst area | worst smoothness | worst compactness | worst concavity | worst concave points | worst symmetry | worst fractal dimension | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Static | 0.200000 | 0.133333 | 0.200000 | 0.333333 | 0.200000 | 0.166667 | 0.100000 | 0.233333 | 0.233333 | 0.266667 | 0.100000 | 0.233333 | 0.233333 | 0.200000 | 0.200000 | 0.200000 | 0.100000 | 0.233333 | 0.133333 | 0.233333 | 0.200000 | 0.166667 | 0.200000 | 0.166667 | 0.100000 | 0.100000 | 0.133333 | 0.166667 | 0.133333 | 0.233333 |
| p-value | 0.594071 | 0.957846 | 0.594071 | 0.070888 | 0.594071 | 0.807963 | 0.998839 | 0.392945 | 0.392945 | 0.239073 | 0.998839 | 0.392945 | 0.392945 | 0.594071 | 0.594071 | 0.594071 | 0.998839 | 0.392945 | 0.957846 | 0.392945 | 0.594071 | 0.807963 | 0.594071 | 0.807963 | 0.998839 | 0.998839 | 0.957846 | 0.807963 | 0.957846 | 0.392945 |
De esta forma podemos observar las variables con mayor valor static y menor p-value, que serán las que mejor separen la clase. Por ejemplo, mean area y mean fractal dimension presentan una mayor diferencia entre sus distribuciones disaciadas por clase.
En este ejercicio deberéis aplicar métodos de reducción de dimensionalidad al conjunto original de datos. El objetivo es reducir el conjunto de atributos a un nuevo conjunto con menos dimensiones.
# Crear dataframe sin la columna "diagnosis" para utilizar solo las variables
bcw_ft = bcw.drop(["diagnosis"], 1)
# Normalizar ambos datasets (max-min)
bcw_ft_n = (bcw_ft - bcw_ft.min()) / (bcw_ft.max() - bcw_ft.min())
bcw_low_corr_n = (bcw_low_corr - bcw_low_corr.min()) / (bcw_low_corr.max() - bcw_low_corr.min())
# Instanciar PCA con n_components = 2 para obtener las dos dimensiones que más varianza aportan
pca = PCA(n_components=2)
# Ajustar el modelo a los datos con todas la variables
pca.fit(bcw_ft_n)
bcw_ft_pca = pca.transform(bcw_ft_n)
print("Filas y dimensiones finales:\t\033[1m", bcw_ft_pca.shape, "\033[0m")
expl = pca.explained_variance_ratio_
print("Suma de la varianza:\t\t\033[1m", sum(expl), "\033[0m")
print("Puntuación:\t\t\t\033[1m", pca.score(bcw_ft_n, bcw["diagnosis"]), "\033[0m")
#Visualizar el grafico de la varianza acumulada
plt.title('Varianza acumulada respecto a las dimensiones (PCA)')
plt.xlabel('Nº de dimensiones')
plt.ylabel('Varianza acumulada')
plt.plot(np.cumsum(pca.explained_variance_ratio_))
plt.show()
Filas y dimensiones finales: (569, 2) Suma de la varianza: 0.7038117901347681 Puntuación: 29.41181779472275
# Ajustar el modelo a los datos sin las variables fuertemente correlacionadas
pca.fit(bcw_low_corr_n)
bcw_low_corr_pca = pca.transform(bcw_low_corr_n)
print("Filas y dimensiones finales:\t\033[1m", bcw_low_corr_pca.shape, "\033[0m")
expl = pca.explained_variance_ratio_
print("Suma de la varianza:\t\t\033[1m", sum(expl), "\033[0m")
print("Puntuación:\t\t\t\033[1m", pca.score(bcw_low_corr_n, bcw["diagnosis"]), "\033[0m")
#Visualizar el grafico de la varianza acumulada
plt.title('Varianza acumulada respecto a las dimensiones (PCA)')
plt.xlabel('Nº de dimensiones')
plt.ylabel('Varianza acumulada')
plt.plot(np.cumsum(pca.explained_variance_ratio_))
plt.show()
Filas y dimensiones finales: (569, 2) Suma de la varianza: 0.6432834866082104 Puntuación: 14.79440111310216
Podemos apreciar la diferencia de varianza acumulada entre las dos dimensiones resultantes dependiendo del dataset utilizado. El que cuenta con todas las variables tiene una varianza acumulada de 0.7, mientras que el dataset al que se le ha extraído las dimensiones más correlacionadas tienen una varianza acumulada de 0.64 con dos variables.
# Guardar los resultados como DataFrame
bcw_pca = pd.DataFrame(data=bcw_ft_pca)
bcw_low_pca = pd.DataFrame(data=bcw_low_corr_pca)
# Crear 2 gráficos, 1 por cada variable
for i in range(bcw_pca.shape[1]):
plt.figure(figsize=(15,5))
plt.title("Variable {} PCA".format(i+1))
# Cada gráfico debe dividir los registros según los valores de la clase (diagnosis) y mostrarlos de forma separada
for j in bcw["diagnosis"].unique():
plt.hist(bcw_pca[i].loc[bcw["diagnosis"]==j], alpha=.75)
plt.legend(bcw["diagnosis"].unique())
plt.xlabel("Magnitud")
plt.ylabel("Frecuencia")
plt.show()
# Crear 2 gráficos, 1 por cada variable
for i in range(bcw_low_pca.shape[1]):
plt.figure(figsize=(15,5))
plt.title("Variable {} PCA".format(i+1))
# Cada gráfico debe dividir los registros según los valores de la clase (diagnosis) y mostrarlos de forma separada
for j in bcw["diagnosis"].unique():
plt.hist(bcw_low_pca[i].loc[bcw["diagnosis"]==j], alpha=.75)
plt.legend(bcw["diagnosis"].unique())
plt.xlabel("Magnitud")
plt.ylabel("Frecuencia")
plt.show()
En la variable 1 PCA del dataset original se aprecia una muy buena diferenciación entre los registros con diagnóstico benigno y maligno, mientras que en la variable 2 PCA es más dificil hacer esta distinción. No obstante, los registros de clase benigno tienen claramente una mayor concentración en el centro de la distribución.
En cuanto al dataset al que se la han extraído previamente los atributos más correlacionados, la diferenciación entre clases no es tan evidente. En la variable 1 PCA hay una mayor superposición que en la misma variable del dataset original, lo que hace que sea más dificil discernir entre la clase. Aún así, se puede ver que los registros con diagnóstico benigno se acumulan mayormente a la izquierda de la distribución, mientras que los de diagnóstico maligno se acumulan más en el centro de forma más aplanada (mayor desviación estándar). La variable 2 PCA se asemeja mucho a la misma variable 2 PCA del dataset original, con ambas distribuciones algo más a la izquierda.
La diferencia entre ambos datasets se hace especialmente notable en la variable 1 PCA, siendo la del dataset original mucho más concluyente.
Existen varios métodos de reducción de dimensionalidad tanto lineales (LDA) como no lineales (GDA).
LDA (Linear Discriminant Analysis) hace una representación de los datos de forma que optimiza la posible clasificación de los datos, tratando de maximizar la distancia entre los datos de distintas clases y minimizando la de los datos de la misma clase.
GDA (Generalized Discriminant Analysis) se utiliza para conjuntos de datos multiclase. Funciona de forma que primero crea un espacio dimensional mayor que el original para tratar de crear nuevas "perspectivas" desde las que, posteriormente, LDA pueda realizar separaciones más claras entre los datos pertenecientes a distintas clases.
Como conclusión, LDA es más conveniente en este caso dado que tan solo disponemos de una clase ("diagnosis"), por lo que con GDA estaríamos complicando la reducción de dimensionalidad innecesariamente.
# Importar librería e instanciar LDA con n_components=1
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
lda = LinearDiscriminantAnalysis(n_components=1)
# LDA solo trabaja con un n_componentes <= nº de clases - 1; en este caso, n_componentes < (2-1)
target
| target | |
|---|---|
| 0 | M |
| 1 | M |
| 2 | M |
| 3 | M |
| 4 | M |
| ... | ... |
| 564 | M |
| 565 | M |
| 566 | M |
| 567 | M |
| 568 | B |
569 rows × 1 columns
bcw["diagnosis"]
0 M
1 M
2 M
3 M
4 M
..
564 M
565 M
566 M
567 M
568 B
Name: diagnosis, Length: 569, dtype: category
Categories (2, object): ['B', 'M']
lda.explained_variance_ratio_
array([1.])
# Ajustar el modelo a los datos con todas la variables
lda.fit(bcw_ft_n, bcw["diagnosis"])
bcw_ft_lda = lda.transform(bcw_ft_n)
print("Filas y dimensiones finales:\t\033[1m", bcw_ft_lda.shape, "\033[0m")
print("Puntuación:\t\t\t\033[1m", lda.score(bcw_ft_n, bcw["diagnosis"]), "\033[0m")
Filas y dimensiones finales: (569, 1) Puntuación: 0.9648506151142355
# Ajustar el modelo a los datos sin las variables fuertemente correlacionadas
lda.fit(bcw_low_corr_n, bcw["diagnosis"])
bcw_low_corr_lda = lda.transform(bcw_low_corr_n)
print("Filas y dimensiones finales:\t\033[1m", bcw_low_corr_lda.shape, "\033[0m")
print("Puntuación:\t\t\t\033[1m", lda.score(bcw_low_corr_n, bcw["diagnosis"]), "\033[0m")
Filas y dimensiones finales: (569, 1) Puntuación: 0.9437609841827768
# Guardar los resultados como DataFrame
bcw_lda = pd.DataFrame(data=bcw_ft_lda)
bcw_low_lda = pd.DataFrame(data=bcw_low_corr_lda)
# Crear el gráfico con el resultado del LDA
for i in range(bcw_lda.shape[1]):
plt.figure(figsize=(15,5))
plt.title("Variable {} LDA".format(i+1))
# Cada gráfico debe dividir los registros según los valores de la clase (diagnosis) y mostrarlos de forma separada
for j in bcw["diagnosis"].unique():
plt.hist(bcw_lda[i].loc[bcw["diagnosis"]==j], alpha=.75)
plt.legend(bcw["diagnosis"].unique())
plt.xlabel("Magnitud")
plt.ylabel("Frecuencia")
plt.show()
# Crear el gráfico con el resultado del LDA
for i in range(bcw_low_lda.shape[1]):
plt.figure(figsize=(15,5))
plt.title("Variable {} LDA".format(i+1))
# Cada gráfico debe dividir los registros según los valores de la clase (diagnosis) y mostrarlos de forma separada
for j in bcw["diagnosis"].unique():
plt.hist(bcw_low_lda[i].loc[bcw["diagnosis"]==j], alpha=.75)
plt.legend(bcw["diagnosis"].unique())
plt.xlabel("Magnitud")
plt.ylabel("Frecuencia")
plt.show()
En el dataset original, la variable 1 LDA es bastante similar a la variable 1 PCA, teniendo la primera una mejor separación de la clase.
Sin embargo, en el dataset sin atributos fuertemente correlacionados la diferencia es mucho mayor. La variable 1 LDA es capaz de separar extraordinariamente bien los registros de distinta clase, mientras que la variable 1 PCA no consigue lograr ese nivel de separación.
Como hemos podido ver, cuando no contamos con variables que estén muy correlacionadas en el dataset, el LDA funciona extraordinariamente bien. PCA también da buenos resultados en este caso, pero cuando la correlación entre las variables es más baja, este método no da tan buenos resultados. Por lo tanto, será más conveniente aplicar el LDA en datasets cuyas variables presenten baja correlación entre ellas y contemos con una sola clase. Por otro lado, PCA es muy potente para datasets con una gran número de dimensiones, pero está algo más limitado que LDA cuando la correlación entre los atributos es baja.
lda.score(bcw_low_corr_n, bcw["diagnosis"])
0.9437609841827768
En este último ejercicio se trata de aplicar un método de aprendizaje supervisado, concretamente el clasificador Decision Tree (un árbol de decisión), para predecir el diagnóstico de cáncer de mama (tumor benigno o maligno) y evaluar la precisión obtenida con el modelo. Para ello usaremos:
# Dividir dataset en train y test
X_train, X_test, y_train, y_test = train_test_split(bcw.drop(["diagnosis"], 1), bcw["diagnosis"], test_size=0.25)
# Generar modelo
dt1 = DecisionTreeClassifier(max_depth=5)
# Validación cruzada
vc = cross_val_score(dt1, X_train, y_train, cv=5)
# Media y desviación estándar
print("Media:\t\t\t\033[1m", vc.mean(), "\033[0m")
print("Desviación estándar:\t\033[1m", vc.std(), "\033[0m")
Media: 0.9341997264021888 Desviación estándar: 0.029473990104478886
# Hacer fit con el conjunto de train
dt1.fit(X_train, y_train)
# Representar gráficamente
plt.subplots(nrows = 1,ncols = 1,figsize = (10, 15), dpi=400)
plot_tree(dt1, feature_names = X_train.columns, class_names = ["Benigno", "Maligno"], filled = True);
# Dividir dataset en train y test
X_train, X_test, y_train, y_test = train_test_split(bcw_pca, bcw["diagnosis"], test_size=0.25)
# Generar modelo
dt2 = DecisionTreeClassifier(max_depth=5)
# Validación cruzada
vc = cross_val_score(dt2, X_train, y_train, cv=5)
# Media y desviación estándar
print("Media:\t\t\t\033[1m", vc.mean(), "\033[0m")
print("Desviación estándar:\t\033[1m", vc.std(), "\033[0m")
# Hacer fit con el conjunto de train
dt2.fit(X_train, y_train)
# Representar gráficamente
plt.subplots(nrows = 1,ncols = 1,figsize = (10, 15), dpi=400)
plot_tree(dt2, feature_names = X_train.columns, class_names = ["Benigno", "Maligno"], filled = True);
Media: 0.9295485636114911 Desviación estándar: 0.010678028710391672
# Dividir dataset en train y test
X_train, X_test, y_train, y_test = train_test_split(bcw_low_pca, bcw["diagnosis"], test_size=0.25)
# Generar modelo
dt3 = DecisionTreeClassifier(max_depth=5)
# Validación cruzada
vc = cross_val_score(dt3, X_train, y_train, cv=5)
# Media y desviación estándar
print("Media:\t\t\t\033[1m", vc.mean(), "\033[0m")
print("Desviación estándar:\t\033[1m", vc.std(), "\033[0m")
# Hacer fit con el conjunto de train
dt3.fit(X_train, y_train)
# Representar gráficamente
plt.subplots(nrows = 1,ncols = 1,figsize = (10, 15), dpi=400)
plot_tree(dt3, feature_names = X_train.columns, class_names = ["Benigno", "Maligno"], filled = True);
Media: 0.8052257181942544 Desviación estándar: 0.04711131866669421
Los resultados obtenidos con el dataset completo no difieren tanto antes como después del PCA. Esto se debe a que las dos variables resultantes reúnen gran parte de la información del dataset para distinguir la clase (varianza aprox. 0.7 entre ambas), por lo que las demás variables no aportan esencialmente tanta información y se pueden prescindir de ellas si empeorar los resultados.
Por otro lado, al eliminar los atributos con mayor correlación se ha perdido una gran parte de la información esencia del dataset, y por ello los resultados obtenidos son bastante peores.
Adicional: como apunte, la reducción de dimensiones llevada a cabo mediante el LDA ofrece unos resultados bastante mejores que los anteriores pese a disponer tan solo de una variable. Cuando hemos graficado este atributo previamente, se diferenciaban claramente ambas clases. A continuación, realizaré el ejercicio anterior con este dataset para confirmarlo.
# Dividir dataset en train y test
X_train, X_test, y_train, y_test = train_test_split(bcw_lda, bcw["diagnosis"], test_size=0.25)
# Generar modelo
dt4 = DecisionTreeClassifier(max_depth=5)
# Validación cruzada
vc = cross_val_score(dt4, X_train, y_train, cv=5)
# Media y desviación estándar
print("Media:\t\t\t\033[1m", vc.mean(), "\033[0m")
print("Desviación estándar:\t\033[1m", vc.std(), "\033[0m")
# Hacer fit con el conjunto de train
dt4.fit(X_train, y_train)
# Representar gráficamente
plt.subplots(nrows = 1,ncols = 1,figsize = (10, 15), dpi=400)
plot_tree(dt4, feature_names = X_train.columns, class_names = ["Benigno", "Maligno"], filled = True);
Media: 0.97890560875513 Desviación estándar: 0.013636154435586842
El mejor modelo es el obtenido con el dataset completo sin el PCA. Sin embargo, el obtenido tras aplicar LDA es incluso mejor a éste, por lo que realizaré este ejercicio con ambos para ver las diferencias.
# Dividir dataset en train y test
X_train, X_test, y_train, y_test = train_test_split(bcw.drop(["diagnosis"], 1), bcw["diagnosis"], test_size=0.25)
y_pred = dt1.predict(X_test)
cm = confusion_matrix(y_test, y_pred)
cm = {'Real: Benigno': cm[0], 'Real: Maligno': cm[1]}
cm = pd.DataFrame.from_dict(cm, orient = 'index', columns = ['Predicción: Benigno', 'Predicción: Maligno'])
print(classification_report(y_test, y_pred))
print("El rendimiento global del modelo es del \033[1m{}%\033[0m".format(round(accuracy_score(y_test,y_pred), 4)*100))
cm
precision recall f1-score support
B 0.99 0.99 0.99 97
M 0.98 0.98 0.98 46
accuracy 0.99 143
macro avg 0.98 0.98 0.98 143
weighted avg 0.99 0.99 0.99 143
El rendimiento global del modelo es del 98.6%
| Predicción: Benigno | Predicción: Maligno | |
|---|---|---|
| Real: Benigno | 96 | 1 |
| Real: Maligno | 1 | 45 |
# Dividir dataset en train y test
X_train, X_test, y_train, y_test = train_test_split(bcw_lda, bcw["diagnosis"], test_size=0.25)
y_pred = dt4.predict(X_test)
cm = confusion_matrix(y_test, y_pred)
cm = {'Real: Benigno': cm[0], 'Real: Maligno': cm[1]}
cm = pd.DataFrame.from_dict(cm, orient = 'index', columns = ['Predicción: Benigno', 'Predicción: Maligno'])
print(classification_report(y_test, y_pred))
print("La precisión total del modelo es del: \033[1m{}%\033[0m".format(round(accuracy_score(y_test,y_pred), 4)*100))
cm
precision recall f1-score support
B 1.00 1.00 1.00 87
M 1.00 1.00 1.00 56
accuracy 1.00 143
macro avg 1.00 1.00 1.00 143
weighted avg 1.00 1.00 1.00 143
La precisión total del modelo es del: 100.0%
| Predicción: Benigno | Predicción: Maligno | |
|---|---|---|
| Real: Benigno | 87 | 0 |
| Real: Maligno | 0 | 56 |